
/*
 *
 * Copyright (C) 2008 Mattias Blomqvist, patr-blo at dsv dot su dot se
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using FlowLib.Events;

namespace ClientExample.Controls
{
    public partial class List : UserControl
    {
        protected int intControlsHeight = 0;
        protected delegate void ChangeItem(object obj);

        public ExpandableItems Items
        {
            get;
            protected set;
        }

        public List()
        {
			IntPtr h = Handle;  // This is for stupid mono stuff. Some how handle isnt created correctly if we dont do this :(
            InitializeComponent();
            Items = new ExpandableItems();
            Items.Added += new EventHandler<FmdcEventArgs<int, ExpandablePanel>>(Items_Added);
            Items.Removed += new EventHandler<FmdcEventArgs<int, ExpandablePanel>>(Items_Removed);

            //vScrollBar1.Value
            this.MouseWheel += new MouseEventHandler(List_MouseWheel);

            this.BackgroundImageChanged += new EventHandler(List_BackgroundImageChanged);
            vScrollBar1.Visible = false;
        }

        void List_BackgroundImageChanged(object sender, EventArgs e)
        {
            if (this.BackgroundImage != null && !Containers.AppSetting.IsRunningOnMono)
            {
                Bitmap bigMap = (Bitmap)this.BackgroundImage;

                Bitmap subBackground = new Bitmap(this.Width, this.Height);
                Graphics graphics = Graphics.FromImage(subBackground);
                graphics.DrawImage(bigMap, new Point(0 - flowLayoutPanel1.Left, 0 - flowLayoutPanel1.Top));
                graphics.Dispose();
                flowLayoutPanel1.BackgroundImageLayout = ImageLayout.Stretch;
                flowLayoutPanel1.BackgroundImage = subBackground;
            }
        }

        void List_MouseWheel(object sender, MouseEventArgs e)
        {
            SetScroll(e.Delta);
        }

        public void SetScroll(int pos)
        {
            int value = pos;
            if (vScrollBar1.Value - pos > vScrollBar1.Maximum)
            {
                vScrollBar1.Value = vScrollBar1.Maximum;
            }
            else if (vScrollBar1.Value - pos < vScrollBar1.Minimum)
            {
                vScrollBar1.Value = vScrollBar1.Minimum;
            }
            else
            {
                vScrollBar1.Value -= pos;
            }
            OnScroll();
        }

        protected void OnScroll()
        {
            flowLayoutPanel1.Top = vScrollBar1.Top - vScrollBar1.Value;
        }

        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            OnScroll();
        }

        void Items_Added(object sender, FmdcEventArgs<int, ExpandablePanel> e)
        {
            ExpandablePanel panel = e.Data;
            intControlsHeight += panel.Height;
            panel.ExpandedChanged += new EventHandler<FmdcEventArgs<int, object>>(panel_ExpandedChanged);
            flowLayoutPanel1.Controls.Add(panel);
            UpdateScrollbarMax();
        }

        void OnAdd(object obj)
        {
            ExpandablePanel panel = obj as ExpandablePanel;
            intControlsHeight += panel.Height;
            panel.ExpandedChanged += new EventHandler<FmdcEventArgs<int, object>>(panel_ExpandedChanged);
            flowLayoutPanel1.Controls.Add(panel);
            UpdateScrollbarMax();
        }

        void OnRemove(object obj)
        {
            ExpandablePanel panel = obj as ExpandablePanel;
            flowLayoutPanel1.Controls.Remove(panel);
            intControlsHeight -= panel.Height;
            UpdateScrollbarMax();
        }

        void panel_ExpandedChanged(object sender, FmdcEventArgs<int, object> e)
        {
            ExpandablePanel panel = sender as ExpandablePanel;
            if (panel == null)
                return;
            int value = panel.Height - e.Action;
            intControlsHeight += value;// +10;
            UpdateScrollbarMax();
        }

        void Items_Removed(object sender, FmdcEventArgs<int, ExpandablePanel> e)
        {
            e.Data.ExpandedChanged -= panel_ExpandedChanged;
            ExpandablePanel panel = e.Data;
            flowLayoutPanel1.Controls.Remove(panel);
            intControlsHeight -= panel.Height;
            UpdateScrollbarMax();
        }

        protected void UpdateScrollbarMax()
        {
            vScrollBar1.Minimum = 1;
            vScrollBar1.Maximum = flowLayoutPanel1.Height - this.Height;
            //if (!(vScrollBar1.Enabled = (intControlsHeight > this.Height)))
            if (!(vScrollBar1.Visible = (intControlsHeight > this.Height)))
            {
                if (vScrollBar1.Value > 1)
                {
                    flowLayoutPanel1.Top = vScrollBar1.Value = 1;
                }
            }
        }

        public class ExpandableItems
        {
            public event EventHandler<FmdcEventArgs<int, ExpandablePanel>> Added;
            public event EventHandler<FmdcEventArgs<int, ExpandablePanel>> Removed;

            public ExpandableItems()
            {
                Added = new EventHandler<FmdcEventArgs<int, ExpandablePanel>>(ExpandableItems_Added);
                Removed = new EventHandler<FmdcEventArgs<int, ExpandablePanel>>(ExpandableItems_Removed);
            }

            void ExpandableItems_Removed(object sender, FmdcEventArgs<int, ExpandablePanel> e) { }
            void ExpandableItems_Added(object sender, FmdcEventArgs<int, ExpandablePanel> e) { }

            public void Add(ExpandablePanel pnl)
            {
                Added(this, new FmdcEventArgs<int, ExpandablePanel>(1, pnl));
            }

            public void Remove(ExpandablePanel pnl)
            {
                Removed(this, new FmdcEventArgs<int, ExpandablePanel>(1, pnl)); 
            }

            public void Clear()
            {
                Removed(this, new FmdcEventArgs<int, ExpandablePanel>(0));
            }
        }
    }
}
